package framework.binding
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.Dictionary;
import flash.utils.describeType;

import framework.event.PropertyEvent;

public class PropertyBinder
{
	private static var dispatcher:EventDispatcher = new EventDispatcher();
	
	private static var binders:Dictionary = new Dictionary(true);
		
	public static function dispatchEvent(event:Event):void
	{
		dispatcher.dispatchEvent(event);
	}
	
	public static function addEventListener(type:String, handler:Function):void
	{
		dispatcher.addEventListener(type, handler);
	}
	
	public static function removeEventListener(type:String, handler:Function):void
	{
		dispatcher.removeEventListener(type, handler);
	}
	
	/**
	 * For example: [Binding(handler="playerPropertyChanged")] 
	 * @param target
	 * 
	 */	
	public static function bind(target:Object):void
	{
		var doc:XML = describeType(target);
		
		if (binders[target] == null)
		{
			binders[target] = { target:target, handlers:[] };
		}
		setInjection(target, doc.variable);
		setInjection(target, doc.accessor);	
	}
	
	public static function unbind(target:Object):void
	{
		var obj:* = binders[target];
		if (obj == null) return;
		
		for each (var fun:String in obj.handlers)
		{
			dispatcher.removeEventListener(PropertyEvent.PROPERTY_CHANGED, obj.target[fun]);
		}
		
		delete binders[target];
	}
	
	private static function setInjection(target:*, list:*):void
	{
		for each (var varItem:* in list)
		{
			if (varItem["metadata"] && varItem.metadata != "") 
			{
				var md:XMLList = varItem.metadata.(@name == "Binding");
				for each (var obj:* in md)
				{
					if (obj.@name != "Binding")
					{
						continue;
					}					
					var fun:String = obj..arg.(@key == "handler").@value;
					var level:String = obj..arg.(@key == "level").@value;
					dispatcher.addEventListener(PropertyEvent.PROPERTY_CHANGED, target[fun], false, level == "" ? 0: int(level));
					
					binders[target].handlers.push(fun);
				}				
			}
		}
	}
	
	public static function release(source:Object):void
	{
		
	}
}
}